﻿using Singer.Core;
using Singer.BackgroundJob.RabbitMQ.BackgroundJobLogs;
using Singer.BackgroundJob.RabbitMQ.BackgroundJobLogs.Dtos;
using Singer.BackgroundJob.RabbitMQ.Contracts;
using Singer.BackgroundJob.RabbitMQ.Contracts.BackgroundJobLogs;

namespace Singer.BackgroundJob.RabbitMQ;

/// <summary>
/// 后台任务执行器 基类
/// </summary>
public abstract class BackgroundJobExecutorBase : IBackgroundJobExecutor
{
    protected readonly BackgroundJobLogManager BackgroundJobLogManager;

    protected BackgroundJobLog JobLog;
    protected CancellationTokenSource StoppingCts;

    /// <summary>
    /// 构造函数
    /// </summary>
    public BackgroundJobExecutorBase(BackgroundJobLogManager backgroundJobLogManager)
    {
        BackgroundJobLogManager = backgroundJobLogManager;
    }

    /// <summary>
    /// 任务执行器 初始化
    /// </summary>
    /// <param name="jobLog">后台任务日志</param>
    /// <param name="stoppingCts">任务取消令牌</param>
    public virtual void Init(BackgroundJobLog jobLog, CancellationTokenSource stoppingCts)
    {
        JobLog = jobLog;
        StoppingCts = stoppingCts;
        StoppingCts.Token.Register(async () => await CancelledAsync());
    }

    /// <summary>
    /// 任务执行 逻辑
    /// </summary>
    public abstract Task ExecuteAsync();


    /// <summary>
    /// 任务取消后 执行逻辑
    /// </summary>
    public virtual async Task CancelledAsync()
    {
        JobLog = await BackgroundJobLogManager.GetAsync(JobLog.Id); // 先将日志实体更新为 外部已更改后的实体，
        await BackgroundJobLogManager.CancelledAsync(JobLog);
    }

    #region 日志记录
    protected virtual Task LogInfoAsync(string content) => LogAsync(BackgroundJobLogType.Info, content);
    protected virtual Task LogWarningAsync(string content) => LogAsync(BackgroundJobLogType.Warning, content);
    protected virtual Task LogErrorAsync(string content) => LogAsync(BackgroundJobLogType.Error, content);
    protected virtual Task LogDebugAsync(string content) => LogAsync(BackgroundJobLogType.Debug, content);
    protected virtual Task LogAsync(BackgroundJobLogType logType, string content)
    {
        var logDto = new BackgroundJobLogDetailDto
        {
            CreateTime = Cores.BeiJingNow,
            LogType = logType,
            Content = content,
            LogId = JobLog.Id
        };
        return BackgroundJobLogManager.AddLogDetailAsync(logDto);
    }
    #endregion
}

/// <summary>
/// 后台任务执行器 泛型基类
/// </summary>
public abstract class BackgroundJobExecutorBase<TArgs> : BackgroundJobExecutorBase, IBackgroundJobExecutor<TArgs>
    where TArgs : IBackgroundJobArgs
{

    /// <summary>
    /// 后台任务参数
    /// </summary>
    protected TArgs Args;

    /// <summary>
    /// 构造函数
    /// </summary>
    public BackgroundJobExecutorBase(BackgroundJobLogManager backgroundJobManager) : base(backgroundJobManager)
    {
    }

    /// <summary>
    /// 任务执行器 初始化
    /// </summary>
    /// <param name="jobLog">后台任务日志</param>
    /// <param name="stoppingCts">任务取消令牌</param>
    public override void Init(BackgroundJobLog jobLog, CancellationTokenSource stoppingCts)
    {
        base.Init(jobLog, stoppingCts);
        Args = JsonUtils.ToModel<TArgs>(jobLog.Args);
    }

}
